// echo aux function only, should not compile alone.
// -r:"../../Backend/System.IO.FileSystem.dll"

//! 编译方法，目前来说只能是自己改上面那行字，把缺的东西都补齐，之后送命令提示符或者用python脚本编译。
//! windows就是一坨shit……连通配符都不支持……不然我至少能写出类似 dotnet C:\Program Files\dotnet\sdk\*\Roslyn\bincore\csc.dll 这样的语法

// -r:"../../The Scroll of Taiwu_Data/Managed/Mono.Cecil.dll" -r:"../../The Scroll of Taiwu_Data/Managed/System.Core.dll"   -r:"../../The Scroll of Taiwu_Data/Managed/System.Composition.AttributedModel.dll" -r:"../../Backend/System.Runtime.dll"
/**
 *  Everyone's Unity Game Plugin
 *  Copyright (C) 2022 Neutron3529
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
//! 这是一个自带文档注释的Mod，虽然代码很shit，但里面有不少注释，或许会对之后准备玩过月逻辑的人有帮助。
//! 所有文档注释会用//!开头，请注意搜索
//! 首先是前后端，前端对后端的调用会先被塞进 ProcessMethodCall，之后分发给对应domain的CallMethod，由CallMethod进行进一步的分发。借助这一点，我们可以快速找到前端调用究竟是在使用哪个函数。
using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using static Utils.Logger;

using Config.EventConfig;
using GameData.Domains.TaiwuEvent;
using GameData.Domains.TaiwuEvent.Enum;

namespace Neutron3529.ChaosEvents {
    public partial class ChaosEvents : EventPackage {
        public 名门.名门 E05(){
            var o=new 名门.名门();
            {
                var taiwuEvent = GameData.Domains.DomainManager.TaiwuEvent.GetEvent("fb38f657-6ed0-41e4-a0c2-c82afb49762f"); // @人物互动-恩义互动
                var lst=taiwuEvent.EventConfig.EventOptions.ToList();
                // for(int i=0;i<1/*o.EventOptions.Length*/;i++){
                //     lst.Insert(lst.Count-1, o.EventOptions[i]);
                // }
                lst.Insert(lst.Count-1, o.EventOptions[0]);
                lst.Insert(lst.Count-1, o.EventOptions[3]);
                taiwuEvent.EventConfig.EventOptions=lst.ToArray();
            }
            return o;
        }
    }
    namespace 名门 {
        public class 名门 : EventItem {
            public 名门() :base("Prof.名门", "70b4d45d-ba15-423d-b94e-b40e348eb9c5", "“我胸怀抱负却苦于晋升无路，若有阁下此言……我定能早跃龙门，不负平生所学！”\n{0}听闻{1}意欲为其美言，自是大喜过望\n若是以名门之威德，于人前力保举荐，或可破例晋升……\n\n(于城镇与门派中举荐人物，可以使其地位发生变化……)"){
                this.EventOptions = new TaiwuEventOption[4];//举贤任能……/力保举荐…… 假意举荐 其他话题……
                for(int i=0;i<this.EventOptions.Length;i++){
                    var op=new TaiwuEventOption {
                        OptionKey = "Option_352905"+(i+1).ToString("02"),
                        OnOptionSelect = new Func<string>(this.OnOptionSelect(i)),
                        OnOptionVisibleCheck = new Func<bool>(this.OnCheckOptionCondition(i)),
                        OnOptionAvailableCheck = new Func<bool>(this.OnCheckEventCondition),
                        GetReplacedContent = new Func<string>(this.Desc(i)),
                        GetExtraFormatLanguageKeys = new Func<List<string>>(this.GetExtraFormatLanguageKeys)
                    };
                    this.EventOptions[i]=op;
                }
            }

            public override string EventContent()=>string.Format(this.content, Name(this.ArgBox.GetCharacter("CharacterId")), Name(GameData.Domains.DomainManager.Taiwu.GetTaiwu()));
            private Func<bool> OnCheckOptionCondition(int index){
                switch(index){
                    case 0:return ()=> {
                        var pd=GameData.Domains.TaiwuEvent.EventHelper.EventHelper.GetCurrentProfessionData();
                        var character=this.EventOptions[index].ArgBox.GetCharacter("CharacterId");
                        return character!=null && pd!=null && pd.TemplateId == 8 && character.GetOrganizationInfo().Grade<8;
                    };
                    case 1:return ()=> {
                        var pd=GameData.Domains.TaiwuEvent.EventHelper.EventHelper.GetCurrentProfessionData();
                        var character=this.EventOptions[index].ArgBox.GetCharacter("CharacterId");
                        return character!=null && pd!=null && pd.TemplateId == 8 && character.GetOrganizationInfo().Grade<8 && character.GetOrganizationInfo().Grade>0;
                    };
                    case 3:return ()=> {
                        var pd=GameData.Domains.TaiwuEvent.EventHelper.EventHelper.GetCurrentProfessionData();
                        var character=this.EventOptions[index].ArgBox.GetCharacter("CharacterId");
                        var location=character.GetLocation();
                        var cid=character.GetId();
                        if(location.IsValid()){
                            var blck=GameData.Domains.DomainManager.Map.GetBlock(location);
                            return character!=null && pd!=null && pd.TemplateId == 8 && blck.CharacterSet!=null && blck.CharacterSet.Any(target_id=>GameData.Domains.DomainManager.Character.TryGetElement_Objects(target_id, out var ch) && ch.GetGender()!=character.GetGender() && GameData.Domains.DomainManager.Character.IsInsect(target_id, cid) );
                        }
                        return false;
                    };
                    default: return ()=>{
                        var pd=GameData.Domains.TaiwuEvent.EventHelper.EventHelper.GetCurrentProfessionData();
                        var character=this.EventOptions[index].ArgBox.GetCharacter("CharacterId");
                        return character!=null && pd!=null && pd.TemplateId == 8;
                    };
                }
            }
            public static short DefKey_Pregnant = (short?)typeof(Config.CharacterFeature.DefKey).GetField("Pregnant",(BindingFlags)(-1))?.GetValue(null)??Config.CharacterFeature.DefKey.Pregnant;
            public static ushort RelationType_HusbandOrWife=((ushort?)(typeof(GameData.Domains.Character.Relation.RelationType).GetField("HusbandOrWife",(BindingFlags)(-1))?.GetValue(null)))??GameData.Domains.Character.Relation.RelationType.HusbandOrWife;
            private unsafe Func<string> OnOptionSelect(int index){
                switch(index){
                    case 0:return ()=>{
                        if(this.EventOptions[index].ArgBox.Contains<bool>("NeutronFlag")){//重入branch
                            this.EventOptions[index].ArgBox.Remove<bool>("NeutronFlag");
                            // TODO
                            var character=this.EventOptions[index].ArgBox.GetCharacter("CharacterId");
                            var cname=Name(character);
                            var tname=Name(GameData.Domains.DomainManager.Taiwu.GetTaiwu());
                            var orgConfig = Config.Organization.Instance[character.GetOrganizationInfo().OrgTemplateId];
                            var memberConfig = Config.OrganizationMember.Instance[orgConfig.Members[character.GetOrganizationInfo().Grade+1]];
                            if(!memberConfig.RestrictPrincipalAmount){
                                GameData.Domains.DomainManager.Organization.ChangeGrade(this.context, character, (sbyte)(character.GetOrganizationInfo().Grade+1), true);
                                return Goto($"“如此大恩，无以为谢……日后但有所托定当全力以赴！”\n见得{tname}点头相应，{cname}自是喜上眉梢，躬身长揖……\n\n{cname}得{tname}一番举荐，未几便为<Character key=CharacterId str=OrgName/>中人所认同\n{tname}言重九鼎，人皆信服\n于是{cname}声威大盛，藉此直上青云……\n\n<color=#lightgrey>(由于{tname}恩威并施作保举荐，{cname}的门派地位上升了……)</color>","（如此甚好……）",index);
                            } else {
                                return Goto($"“如此大恩，无以为谢……日后但有所托定当全力以赴！”\n见得{tname}点头相应，{cname}自是喜上眉梢，躬身长揖……\n\n“怕是本门自有隐情在此……门不容车,而不可逾越……”\n见{tname}举荐不成，{cname}自是失望不已，落寞而去……\n\n<color=#lightgrey>（凭借太吾威德尚且未能在<Character key=CharacterId str=OrgName/>派中举荐{cname}，{tname}感到一丝不解……）</color>","（若有所思……）",index);
                            }
                        } else {//初入branch
                            this.EventOptions[index].ArgBox.Set("NeutronFlag",false);
                            return this.guid;//重入
                        }
                    };
                    case 1:return ()=>{
                        this.EventOptions[index].ArgBox.Remove<bool>("NeutronFlag");
                        var character=this.EventOptions[index].ArgBox.GetCharacter("CharacterId");
                        var cname=Name(character);
                        var tname=Name(GameData.Domains.DomainManager.Taiwu.GetTaiwu());
                        var orgConfig = Config.Organization.Instance[character.GetOrganizationInfo().OrgTemplateId];
                        var memberConfig = Config.OrganizationMember.Instance[orgConfig.Members[0]];
                        GameData.Domains.DomainManager.Organization.ChangeGrade(this.context, character, (sbyte)0, true);
                        return Goto($"“如此大恩，无以为谢……日后但有所托定当全力以赴！”\n见得{tname}点头相应，{cname}自是喜上眉梢，躬身长揖……\n\n「你听说了吗，{cname}竟然与{tname}有所勾结……」<Character key=CharacterId str=OrgName/>中忽然传出了一些奇妙的风闻，{cname}为了避嫌，暂时退隐\n\n<color=#lightgrey>（{cname}为了自证清白，自请降为{memberConfig.GradeName}）</color>","（若有所思……）",index);
                    };
                    case 2:return ()=>{
                        this.EventOptions[index].ArgBox.Remove<bool>("NeutronFlag");
                        return "fb38f657-6ed0-41e4-a0c2-c82afb49762f"; // @人物互动-恩义互动
                    };
                    case 3:return ()=>{
                        var pd=GameData.Domains.TaiwuEvent.EventHelper.EventHelper.GetCurrentProfessionData();
                        // var taiwuChar=this.EventOptions[index].ArgBox.GetCharacter("RoleTaiwu");
                        var character=this.EventOptions[index].ArgBox.GetCharacter("CharacterId");
                        var location=character.GetLocation();
                        var cid=character.GetId();
                        var blck=GameData.Domains.DomainManager.Map.GetBlock(location);
                        var cname=Name(character);
                        // var tname=Name(taiwuChar);
                        var currDate=GameData.Domains.DomainManager.World.GetCurrDate();
                        var lifeRecordCollection = GameData.Domains.DomainManager.LifeRecord.GetLifeRecordCollection();
                        var married=0;
                        var pregnanted=0;
                        var borned=0;
                        var mc=character;
                        var pm=character;
                        var bm=character;
                        var pf=character;
                        var bf=character;
                        var spouseOrgInfo=character.GetOrganizationInfo();
                        var orgConfig = Config.Organization.Instance[spouseOrgInfo.OrgTemplateId];
                        var spouseOrgMemberCfg = Config.OrganizationMember.Instance[orgConfig.Members[spouseOrgInfo.Grade]];
                        foreach(var target_id in blck.CharacterSet){
                            if(GameData.Domains.DomainManager.Character.TryGetElement_Objects(target_id, out var ch) && ch.GetGender()!=character.GetGender() && GameData.Domains.DomainManager.Character.IsInsect(target_id, cid) ){
                                if(ch.GetOrganizationInfo().Grade<spouseOrgInfo.Grade){
                                    try {
                                        var selfNewOrgInfo = new GameData.Domains.Character.OrganizationInfo(spouseOrgInfo.OrgTemplateId, (!spouseOrgMemberCfg.RestrictPrincipalAmount || spouseOrgMemberCfg.DeputySpouseDowngrade >= 0) ? spouseOrgInfo.Grade : (sbyte)0, spouseOrgMemberCfg.DeputySpouseDowngrade < 0, spouseOrgInfo.SettlementId);
                                        GameData.Domains.DomainManager.Organization.ChangeOrganization(context, ch, selfNewOrgInfo);
                                        ch.SetOrganizationInfo(selfNewOrgInfo, context);
                                    } catch(Exception ex) {
                                        logwarn("圣婚功能并不完善，存在BUG。请不要在{NameG(ch)}在场的情况下对{NameG(character)}使用圣婚。报错信息如下：");
                                        logex(ex);
                                    }
                                }
                                if(!GameData.Domains.DomainManager.Character.HasRelation(cid,target_id,RelationType_HusbandOrWife)){
                                    mc=ch;
                                    GameData.Domains.DomainManager.Character.AddHusbandOrWifeRelations(this.context, cid, target_id);
                                    married++;
                                } else if(ch.GetAgeGroup()!=0){
                                    var mother=(character.GetGender()==0)?character:ch;
                                    var father=(character.GetGender()!=0)?character:ch;
                                    if(GameData.Domains.DomainManager.Character.TryGetPregnantState(mother.GetId(), out var ps)){
                                        bm=mother;
                                        bf=father;
                                        borned++;
                                        ps.ExpectedBirthDate=GameData.Domains.DomainManager.World.GetCurrDate()+1;
                                    }else{
                                        pm=mother;
                                        pf=father;
                                        pregnanted++;
                                        GameData.Domains.DomainManager.Character.CreatePregnantState(this.context, mother, father, false);
                                        mother.AddFeature(this.context, DefKey_Pregnant);
                                    }
                                    mother.MakeLove(this.context,father,false);
                                    lifeRecordCollection.AddMakeLoveIllegal(mother.GetId(), currDate, father.GetId(), location);
                                }
                            }
                        }
                        return Goto((married>0?"「我也是倾慕"+(married>1?$"{married}位":Name(mc))+(character.GetGender()==0?"哥哥":"妹妹")+$"许多时日了，若无<Character key=RoleTaiwu str=Name/>证婚，怕我们仍被礼教束缚着……」\n\n":string.Empty)+(pregnanted>0?(pregnanted>1?$"{NameG(character)}与{pregnanted}位"+(character.GetGender()==0?"哥哥":"妹妹"):$"{NameG(pm)}与{NameG(pf)}")+$"一起重温了圣婚仪式，情动之下，春光四溢\n一阵荒唐之后，{NameG(pm)}"+(pregnanted>1?$"等{pregnanted}人竟都":"竟")+"有了身孕\n\n":string.Empty)+(borned>0?(character.GetGender()==0?$"因为受到多位哥哥的滋润{NameG(character)}的肚子很快就鼓了起来\n\n":(borned>1?$"{NameG(bm)}等{borned}位妹妹":NameG(bm))+$"不顾自己身怀六甲，与{NameG(character)}动情春宵许久，已致腹中胎儿有早产的迹象\n所幸对圣婚子嗣，是否早产并不会有太多影响\n\n"):string.Empty)+$"<color=#lightgrey>（{cname}高兴地与"+(character.GetGender()==0?"好哥哥":"小妹妹")+"生活在了一起）</color>","（如此甚好……）",index);
                    };
                    default: return ()=>string.Empty;
                }
            }
            public override Func<string> Desc(int index){
                switch(index){
                    case 0:
                        return ()=>{
                            return this.EventOptions[index].ArgBox.Contains<bool>("NeutronFlag")?"（力保举荐……）":"（举贤任能……）";
                        };
                    case 1:
                        return ()=>{
                            return "（假意举荐……）";
                        };
                    case 2:
                        return ()=>{
                            return "（其他话题……）";
                        };
                    case 3:
                        return ()=>{
                            return "（见证圣婚……）";
                        };
                    default: return ()=>string.Empty;
                }
            }
        }
    }
}
